/*! \file constant.h
	\author HiddenSeeker

	Declares a constant type
*/
#include "../abstractnode.h"
#include "classtype.h"
#include <string>
#pragma once

/*! Basic class for constant behaviour
*/
class ConstantCommand
{
 protected:
		unsigned short m_constructor; //!< Method ref for constructor
		unsigned short m_class;       //!< Class for new
 public:
	    /*! Frees associated data
		*/
	    virtual  void freeData();
		/*! Writes a constant
			\param[in] number number of associated node
			\param[in] line   line   of code
			\param[in] pos    position in code
			\param[in] s      stream
		*/
	    virtual void write(int number,int line,int pos,GraphStream * s)=0;

		/*! Returns unknown type
		 */
		virtual std::string getType(ParentData * data)=0;
		/*! Fills a constant table
		 */
		virtual void fillCTable(ParentData * data);
        /*! Produces a code for method
		 */
		virtual void produceCode(ParentData * data)=0;
		/*!  Tries to negate
			 \return true if successfully negated
		*/
		virtual  bool negate();
		/*!  Destructor
		*/
		virtual ~ConstantCommand();
};

class IntegralCommand: public ConstantCommand
{
 private:
	      long long  m_ll;
		  unsigned short m_index;
 public:
	      inline IntegralCommand(long long ll)  { m_ll=ll;}
		  void write(int number,int line,int pos,GraphStream * s);
		  /*! Fills a constant table
		   */
	      virtual void fillCTable(ParentData * data);
        /*! Produces a code for method
 		 */
		 virtual void produceCode(ParentData * data);
		  std::string getType(ParentData * data);
		  bool negate();
};
class FloatCommand: public ConstantCommand
{
 private:
		  double       m_dbl;
		  unsigned short m_index;
 public:
     	 inline FloatCommand(double dbl)  { m_dbl=dbl; }
		 void write(int number,int line,int pos,GraphStream * s);
		 /*! Fills a constant table
		  */
		 virtual void fillCTable(ParentData * data);
         /*! Produces a code for method
		  */
		 virtual void produceCode(ParentData * data);
		 std::string getType(ParentData * data);
		 bool negate();
};
class BooleanCommand: public ConstantCommand
{
 private:
	     bool   m_b;
 public:
	     inline BooleanCommand(bool  b)     { m_b=b;}
		 void write(int number,int line,int pos,GraphStream * s);
		 /*! Fills a constant table
		  */
		 virtual void fillCTable(ParentData * data);
        /*! Produces a code for method
		 */
		virtual void produceCode(ParentData * data);
		 /*! Returns unknown type
		 */
		virtual std::string getType(ParentData * data);
};
class SLiteralsCommand: public  ConstantCommand
{
 protected:
		 std::string * m_str;
 public:
	     inline SLiteralsCommand(std::string * s)  {m_str=s;}
		 void freeData();
};

class CharacterCommand: public SLiteralsCommand
{
 public:
	     inline CharacterCommand(std::string * s) : SLiteralsCommand(s)
		 { while(s->size()>1) s->erase(s->length()-1); }
		 void write(int number,int line,int pos,GraphStream * s);
		 /*! Returns unknown type
		  */
		 virtual std::string getType(ParentData * data);
		 /*! Fills a constant table
		  */
	     virtual void fillCTable(ParentData * data);
        /*! Produces a code for method
		 */
		virtual void produceCode(ParentData * data);
};

class StringCommand: public SLiteralsCommand
{
 private:
	     unsigned short m_index;
 public:
	     inline StringCommand(std::string * s) : SLiteralsCommand(s)
		 {  }
		 void write(int number,int line,int pos,GraphStream * s);
		 /*! Fills a constant table
		  */
	     virtual void fillCTable(ParentData * data);
		 std::string getType(ParentData * data);
         /*! Produces a code for method
		  */
		 virtual void produceCode(ParentData * data);
};


class Constant: public AbstractNode
{
 private:
	      ConstantCommand * m_behaviour;
 public:
	      inline Constant(const YYLTYPE & pos, bool ischar ,std::string * s): 
		                  AbstractNode(pos)
		  {
			  if (ischar) 
				  m_behaviour=new CharacterCommand(s); 
			  else 
				  m_behaviour=new StringCommand(s);
		  }
		  inline Constant(const YYLTYPE & pos, bool b): AbstractNode(pos)
		  {
			  m_behaviour=new BooleanCommand(b);
		  }
		  inline Constant(const YYLTYPE & pos, long long ll): AbstractNode(pos)
		  {
			  m_behaviour=new IntegralCommand(ll);
		  }
		  inline Constant(const YYLTYPE & pos, double dbl): AbstractNode(pos)
		  {
			 m_behaviour=new  FloatCommand(dbl);
		  }
		  /*! Transforms a code, if needed to
			  \return true on success
		  */
		  virtual bool checkLogic(ParentData * data); 
		  AbstractNode * negate(const YYLTYPE & pos);
		  /*! Fills a constant table
		  */
		  virtual void fillConstant(ParentData * data);
		  /*! Produces a code for method
		   */
		  virtual void produceCode(ParentData * data);
		  /*! Returns  type
		   */
		  virtual std::string getType(ParentData * data);
		  /*! Writes a declaration to stream
	       */
	      void  write(GraphStream * s);
		  ~Constant();
		  
};
